package DataModel.LayoutManager;

import java.awt.Point;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;

import VisibilityGraph.NeighboursHash;

import DataModel.CommonLibrary.*;
import DataModel.CommonLibrary.CommonDefs.Layer;

public class CLayoutManager 
{
	/***************************************************/
	/****** C'tors *************************************/
	/***************************************************/
	public CLayoutManager(LinkedList<CRectangle> recsRawList)
	{
		Initialize(recsRawList);		
	}
	
	
	/***************************************************/
	/****** Members ************************************/
	/***************************************************/
	private CRectanglesSortedList m_xSorted = new CRectanglesSortedList();
	private CRectanglesSortedList m_ySorted = new CRectanglesSortedList();
	
	private HashMap<Long, CRectangle> m_recsHashMap = new HashMap<Long, CRectangle>();
	
	private VisibilityGraph.NeighboursHash m_neighbours = null;
	
	/***************************************************/
	/****** Getters / Setters **************************/
	/***************************************************/
	public CRectanglesSortedList GetXSorted() {
		return m_xSorted;
	}

	public void SetXSorted(CRectanglesSortedList sorted) {
		m_xSorted = sorted;
	}

	public CRectanglesSortedList GetYSorted() {
		return m_ySorted;
	}

	public void SetYSorted(CRectanglesSortedList sorted) {
		m_ySorted = sorted;
	}
	
	/***************************************************/
	/****** Public Functions ***************************/
	/***************************************************/
	
	/**
	 * Get rectangle form rectangles hash map by id
	 * @param recID - needed rectangle ID
	 * @return needed rectangle object 
	 */
	public CRectangle GetRectangle(long recID)
	{
		return m_recsHashMap.get(recID);
	}
	
	public CRectangle GetRectangle(CRectangle rectangle)
	{
		for (CRectangle rec : m_xSorted.GetRecsSortedList()) 
		{
			if(rec.equals(rectangle))
				return rec;
		}
		
		return null;
	}
	
	public LinkedList<CRectangle> GetNeighbours(CRectangle rec, char direction)
	{
		return m_neighbours.getNeighbours(rec, direction);
	}
	
	public LinkedList<CRectangle> GetRecsInLayer(Layer layer)
	{
		LinkedList<CRectangle> recs = new LinkedList<CRectangle>();
		
		for (CRectangle rectangle : m_xSorted.GetRecsSortedList()) 
		{
			if(rectangle.getLayer() == layer)
				recs.add(rectangle);
		}
		
		return recs;
	}
	
	public CRectangle GetRecByPlace(Point point, Layer layer)
	{
		for (CRectangle rec : m_xSorted.GetRecsSortedList()) 
		{
			if(rec.isInnerPoint(point) && rec.getLayer() == layer)
				return rec;
		}
		
		return null;
	}
	
	/***************************************************/
	/****** Utils **************************************/
	/***************************************************/
	
	/**
	 * Initializes Layout manager data structures 
	 * @param inputURL - input textual layout (URL or Path)
	 */
	private void Initialize(LinkedList<CRectangle> recsRawList)
	{
		// Sort raw rectangles list into sorted X and sorted Y
		SortRawRecsList(recsRawList);
		
		// make neighbours graph
		m_neighbours = new NeighboursHash(recsRawList);
	}
	
	/**
	 * Sort raw rectangles list
	 * @param recsRawList - raw rectangles list
	 */
	private void SortRawRecsList(LinkedList<CRectangle> recsRawList)
	{
		if(recsRawList == null)
			return;

		/********* Sort X *********/		
		LinkedList<CRectangle> tempXList = new LinkedList<CRectangle>(recsRawList);
		CRectangle leftesEdgeRec;
		
		while(!tempXList.isEmpty())
		{
			leftesEdgeRec = CGeometricOperations.GetLeftestEdgeRectangle(tempXList);
			
			if(leftesEdgeRec != null)
			{
				GetXSorted().Add(leftesEdgeRec);
				tempXList.remove(leftesEdgeRec);
			}
		}
		
		/********* Sort Y *********/
		LinkedList<CRectangle> tempYList = new LinkedList<CRectangle>(recsRawList);
		CRectangle bottomestEdgeRec;
		
		while (!tempYList.isEmpty())
		{	
			bottomestEdgeRec = CGeometricOperations.GetBottomestEdgeRectangle(tempYList);
			
			if(bottomestEdgeRec != null)
			{
				GetYSorted().Add(bottomestEdgeRec);
				tempYList.remove(bottomestEdgeRec);
			}
		}
	}
}
























